import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(style='whitegrid', font_scale=1.3, palette='Set2')
%matplotlib inline
import plotly
import plotly.express as px
import requests
from time import sleep
from tqdm import tqdm
import json
Второй курс — самое время задуматься о будущей профессии и проанализировать существующие предложения. Дело тут даже не в том, чтобы найти интересную стажировку. В первую очередь сейчас стоит подумать о том, в какую сторону развиваться дальше. Например, если вы хотите работать в какой-либо конкретной профессии, то наверняка стоит развивать какие-то определенные навыки, и даже выбрать подходящую кафедру. Анализ существующих вакансий поможет определить, какие навыки вам нужны.
В данном задании вам нужно проанализировать вакансии на сайте hh.ru с использованием официального API.
Внимание! При работе с API не забывайте делать паузы между запросами, чтобы не задудосить сервер HeadHunter. Если вас заблокируют, это не будет являться уважительной причиной переноса дедлайна.
Мы будем работать только с вакансиями. Для этого не требуется регистрироваться и получать токен. Ниже приведен краткий пример работы с API. Подробное описание работы с вакансиями, включая параметры запросов и формат ответа можно почитать в документации.
Например, мы хотим найти вакансии по запросу Data Scientist в Москве. Тогда первую страницу поиска из 10 вакансий на страницу мы можем получить с запроса к API:
URL = 'https://api.hh.ru/vacancies'
params = {
'text': "Data Scientist",
'area': 1,
'page': 0,
'per_page': 10
}
req = requests.get(URL, params)
data = json.loads(req.content.decode())
Если все прошло успешно, полученный словарь будет иметь следующие ключи
data.keys()
dict_keys(['items', 'found', 'pages', 'per_page', 'page', 'clusters', 'arguments', 'alternate_url'])
Можем посмотреть на краткое описание первой вакансии
data['items'][0]
{'id': '49423067',
'premium': False,
'name': 'Data Scientist',
'department': None,
'has_test': False,
'response_letter_required': False,
'area': {'id': '1', 'name': 'Москва', 'url': 'https://api.hh.ru/areas/1'},
'salary': {'from': None, 'to': 390000, 'currency': 'RUR', 'gross': False},
'type': {'id': 'open', 'name': 'Открытая'},
'address': None,
'response_url': None,
'sort_point_distance': None,
'published_at': '2022-03-17T12:37:57+0300',
'created_at': '2022-03-17T12:37:57+0300',
'archived': False,
'apply_alternate_url': 'https://hh.ru/applicant/vacancy_response?vacancyId=49423067',
'insider_interview': None,
'url': 'https://api.hh.ru/vacancies/49423067?host=hh.ru',
'alternate_url': 'https://hh.ru/vacancy/49423067',
'relations': [],
'employer': {'id': '2324020',
'name': 'Точка',
'url': 'https://api.hh.ru/employers/2324020',
'alternate_url': 'https://hh.ru/employer/2324020',
'logo_urls': {'240': 'https://hhcdn.ru/employer-logo/3414734.jpeg',
'90': 'https://hhcdn.ru/employer-logo/3414733.jpeg',
'original': 'https://hhcdn.ru/employer-logo-original/743443.jpg'},
'vacancies_url': 'https://api.hh.ru/vacancies?employer_id=2324020',
'trusted': True},
'snippet': {'requirement': 'Есть опыт работы с методами машинного обучения и основными инструментами <highlighttext>data</highlighttext> science: Scikit-learn, XGBoost, CatBoost и т.п. ',
'responsibility': 'Придумывать и проверять гипотезы, которые позволят построить новые скоринговые модели и улучшить текущие. В результате они должны определять благонадёжность компаний...'},
'contacts': None,
'schedule': {'id': 'fullDay', 'name': 'Полный день'},
'working_days': [],
'working_time_intervals': [],
'working_time_modes': [],
'accept_temporary': False}
Сколько всего найдено вакансий
data['found']
285
Количество страниц в результатах поиска
data['pages']
29
Из результатов можем сделать удобную таблицу, причем в дальнейшем можно оставить только те колонки, которые необходимы для анализа.
df = pd.json_normalize(data['items'])
df.head()
| id | premium | name | department | has_test | response_letter_required | address | response_url | sort_point_distance | published_at | ... | address.raw | address.metro.station_name | address.metro.line_name | address.metro.station_id | address.metro.line_id | address.metro.lat | address.metro.lng | address.metro_stations | address.id | address.metro | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 49423067 | False | Data Scientist | NaN | False | False | NaN | None | None | 2022-03-17T12:37:57+0300 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 1 | 53929493 | True | Data Scientist (CV+NLP) | NaN | False | False | NaN | None | None | 2022-03-16T12:35:21+0300 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 2 | 53947371 | True | Data Scientist (Корпоративный бизнес) | NaN | False | False | NaN | None | None | 2022-03-16T17:25:13+0300 | ... | Москва, Кутузовский проспект, 32к1 | Кутузовская | Филевская | 4.73 | 4 | 55.740544 | 37.534100 | [{'station_name': 'Кутузовская', 'line_name': ... | 731097 | NaN |
| 3 | 53809111 | False | Data scientist / Product analyst | NaN | False | False | NaN | None | None | 2022-03-17T11:45:23+0300 | ... | Москва, Нижняя Красносельская улица, 35с9 | Бауманская | Арбатско-Покровская | 3.17 | 3 | 55.772405 | 37.679040 | [{'station_name': 'Бауманская', 'line_name': '... | 743543 | NaN |
| 4 | 53211742 | False | Junior Data scientist/ Младший риск-аналитик | NaN | False | True | NaN | None | None | 2022-03-16T11:16:44+0300 | ... | Москва, улица 8 Марта, 1с12 | Динамо | Замоскворецкая | 2.34 | 2 | 55.789704 | 37.558212 | [{'station_name': 'Динамо', 'line_name': 'Замо... | 1551673 | NaN |
5 rows × 63 columns
Для получения полного описания вакансии потребуется задать отдельный запрос, используя ее id.
vacancy = df['id'].iloc[0]
vacancy_url = f'https://api.hh.ru/vacancies/{vacancy}'
req = requests.get(vacancy_url)
vacancy_info = json.loads(req.content.decode())
vacancy_info
{'id': '49423067',
'premium': False,
'billing_type': {'id': 'standard_plus', 'name': 'Стандарт плюс'},
'relations': [],
'name': 'Data Scientist',
'insider_interview': None,
'response_letter_required': False,
'area': {'id': '1', 'name': 'Москва', 'url': 'https://api.hh.ru/areas/1'},
'salary': {'from': None, 'to': 390000, 'currency': 'RUR', 'gross': False},
'type': {'id': 'open', 'name': 'Открытая'},
'address': None,
'allow_messages': True,
'site': {'id': 'hh', 'name': 'hh.ru'},
'experience': {'id': 'between3And6', 'name': 'От 3 до 6 лет'},
'schedule': {'id': 'fullDay', 'name': 'Полный день'},
'employment': {'id': 'full', 'name': 'Полная занятость'},
'department': None,
'contacts': None,
'description': '<p>Ищем специалиста по Data Science, чтобы строить и улучшать модели машинного обучения, которые помогут усовершенствовать наш продукт и внутренние процессы. Мы стремимся к тому, чтобы мы стали быстрее и удобнее для клиентов. И в этом нам нужна твоя помощь.</p> <p><strong>Что нужно делать</strong></p> <p>Придумывать и проверять гипотезы, которые позволят построить новые скоринговые модели и улучшить текущие. В результате они должны определять благонадёжность компаний по данным о бизнесе.</p> <p>Ты будешь доставать данные из баз и других источников, приводить их к нужному виду, анализировать и затем строить модели. Тебе предстоит планировать и ставить эксперименты, анализировать результаты и их статистическую значимость. Использовать feature engineering, model selection и fine tuning.</p> <p><strong>Ты подойдешь, если</strong></p> <ul> <li> <p>Знаешь Python, умеешь обрабатывать данные с помощью pandas, NumPy, Plotly.</p> </li> <li> <p>У тебя есть опыт работы с SQL.</p> </li> <li> <p>Есть опыт работы с методами машинного обучения и основными инструментами data science: Scikit-learn, XGBoost, CatBoost и т.п.</p> </li> <li> <p>Разбираешься в математической статистике, теории вероятностей и знаешь, как проводить A/B тестирования.</p> </li> </ul> <p><strong>Будет плюсом, если</strong></p> <ul> <li> <p>Ты понимаешь принципы работы нейросетей и уже имеешь опыт с одним или несколькими фреймворками для глубокого обучения: TensorFlow или PyTorch.</p> </li> <li> <p>Умеешь вводить модели машинного обучения в работу production.</p> </li> </ul> <p><strong>Что будет твоим в Точке</strong></p> <ul> <li> <p>Зарплата от 100 000 ₽. Расскажи на собеседовании, какая зарплата будет комфортной для тебя. А мы определим твой грейд по хард и софт скиллам и назовём точную сумму.</p> </li> <li> <p>Официальное трудоустройство и бесплатная страховка здоровья даже за границей.</p> </li> <li> <p>Удобный график: гибкое начало и окончание рабочего дня.</p> </li> <li> <p>Современный и уютный офис со спортзалом и библиотекой, кофе-поинтами, кухнями и зонами отдыха.</p> </li> <li> <p>Гибкие методы управления: мы используем Agile и SCRUM, чтобы каждый день создавать новое и быстро реагировать на изменения.</p> </li> <li> <p>Бесплатное корпоративное обучение: мы ездим на IT-конференции, собираемся на митапы, раздаем призы на хакатонах и проходим курсы за счёт компании.</p> </li> <li> <p>Возможность принимать решения без тысячи согласований и предлагать идеи: от простых до самых амбициозных.</p> </li> </ul> <p>И всё это в комфортных условиях без бюрократии, дресс-кода и начальников.</p>',
'branded_description': '\n<style>\n.tmpl_hh_wrapper p,\n.tmpl_hh_wrapper a,\n.tmpl_hh_wrapper img,\n.tmpl_hh_wrapper ol,\n.tmpl_hh_wrapper ul,\n.tmpl_hh_wrapper li {\n margin: 0;\n padding: 0;\n border: 0;\n font-size: 100%;\n font: inherit;\n vertical-align: baseline;\n}\n\n.hht-vacancydescription {\n padding: 0px;\n}\n\n.tmpl_hh_wrapper .l-cell,\n.tmpl_hh_wrapper .l-paddings {\n padding: 0px !important;\n}\n\n.tmpl_hh_wrapper .b-vacancy-desc-wrapper {\n margin-top: 0px !important; \n}\n\n.tmpl_hh_wrapper .b-vacancy-desc {\n overflow: visible !important;\n line-height: inherit;\n}\n\n.tmpl_hh_content ol li b,\n.tmpl_hh_content ol li strong,\n.tmpl_hh_content ol li p b,\n.tmpl_hh_content ol li p strong,\n.tmpl_hh_content ul li b,\n.tmpl_hh_content ul li strong,\n.tmpl_hh_content ul li p b,\n.tmpl_hh_content ul li p strong {\n font-weight: normal;\n font-size: inherit !important;\n color: inherit !important;\n margin: 0 !important;\n text-transform: none;\n line-height: inherit;\n}\n\n.tmpl_hh_content ol li p,\n.tmpl_hh_content ul li p {\n font-weight: normal;\n margin: 0;\n}\n\n.tmpl_hh_content p b,\n.tmpl_hh_content p strong {\n margin: 0 0 0;\n padding: 28px 0 8px;\n}\n\n.tmpl_hh_wrapper {\n width: 100%;\n margin: 0 auto;\n max-width: 690px;\n position: relative;\n word-break: normal;\n color: #333333;\n overflow: hidden;\n font-family: \'Verdana\', sans-serif;\n font-size: 14px;\n line-height: 20px;\n -webkit-font-smoothing: antialiased;\n}\n\n.tmpl_hh_wrapper img {\n width: 100%;\n display: block;\n}\n\n.tmpl_hh_content {\n padding: 41px 40px 34px;\n position: relative;\n z-index: 1;\n}\n\n.tmpl_hh_content p:first-child,\n.tmpl_hh_content>strong:first-child,\n.tmpl_hh_content div>strong:first-child {\n margin-top: 0 !important;\n}\n\n.tmpl_hh_content p,\n.tmpl_hh_content b,\n.tmpl_hh_content strong {\n margin: 12px 0 12px;\n}\n\n.tmpl_hh_content b, \n.tmpl_hh_content strong {\n display: inline-block;\n font-weight: bold;\n font-size: 24px;\n line-height: 32px;\n}\n\n.tmpl_hh_content ol,\n.tmpl_hh_content ul {\n margin-left: 15px;\n list-style: none !important;\n}\n\n.tmpl_hh_content ol {\n counter-reset: list_counter;\n}\n\n.tmpl_hh_content li {\n position: relative;\n margin-bottom: 12px;\n}\n\n.tmpl_hh_content ul ul,\n.tmpl_hh_content ul ol,\n.tmpl_hh_content ol ol,\n.tmpl_hh_content ol ul {\n margin-top: 12px;\n}\n\n.tmpl_hh_content ol>li {\n counter-increment: list_counter; \n}\n\n.tmpl_hh_content li:before {\n position: absolute;\n left: -15px;\n top: 0;\n}\n\n.tmpl_hh_content ul>li:before {\n content: "";\n height: 5px;\n width: 5px;\n background: #333333;\n opacity: 0.45;\n border-radius: 50%;\n top: 7px;\n}\n\n.tmpl_hh_content ol>li:before {\n content: counter(list_counter)\'.\';\n left: auto;\n right: 100%;\n margin-right: 2px;\n}\n\n.tmpl_hh_header {\n padding: 6.5% 40px 0;\n background: url(https://hhcdn.ru/ichameleon/152526.png) 0 0 no-repeat;\n background-size: 21% auto;\n}\n\n.tmpl_hh_header_logo {\n position: relative;\n width: 28.6%;\n}\n\n.tmpl_hh_footer {\n position: relative;\n background: url(https://hhcdn.ru/ichameleon/152638.jpg);\n height: 0;\n padding-bottom: 56.4%;\n background-size: 100%;\n background-repeat: no-repeat;\n}\n\np.tmpl_hh_foonote {\n position: absolute;\n bottom: 10px;\n left: 4.6%;\n font-size: 9px;\n line-height: 9px;\n z-index: 1;\n}\n\n@media (max-width: 699px) {\n .tmpl_hh_content p b, .tmpl_hh_content p strong {\n padding: 18px 0 3px;\n }\n\n .tmpl_hh_content b, .tmpl_hh_content strong {\n font-size: 20px;\n line-height: 28px;\n }\n\n .tmpl_hh_header {\n padding: 12.9% 0 0% 0%;\n background: url(https://hhcdn.ru/ichameleon/152842.png) 0 0 no-repeat;\n background-size: 26% auto;\n }\n\n .tmpl_hh_header_logo {\n width: 50.2%; \n }\n\n .tmpl_hh_content {\n padding: 43px 0% 0px;\n }\n\n .tmpl_hh_footer {\n background: url(https://hhcdn.ru/ichameleon/152640.jpg);\n padding-bottom: 129.4%;\n background-size: 106%;\n background-repeat: no-repeat;\n margin-top: -4%;\n }\n\n p.tmpl_hh_foonote {\n position: relative;\n top: 0;\n left: 0;\n margin-top: 2%;\n }\n}\n</style>\n\n\n<div class="tmpl_hh_wrapper">\n <div class="tmpl_hh_header">\n <div class="tmpl_hh_header_logo"><img src="https://hhcdn.ru/ichameleon/152525.svg" alt=""></div>\n </div>\n <div class="tmpl_hh_content">\n <p>Ищем специалиста по Data Science, чтобы строить и улучшать модели машинного обучения, которые помогут усовершенствовать наш продукт и внутренние процессы. Мы стремимся к тому, чтобы мы стали быстрее и удобнее для клиентов. И в этом нам нужна твоя помощь.</p> <p><strong>Что нужно делать</strong></p> <p>Придумывать и проверять гипотезы, которые позволят построить новые скоринговые модели и улучшить текущие. В результате они должны определять благонадёжность компаний по данным о бизнесе.</p> <p>Ты будешь доставать данные из баз и других источников, приводить их к нужному виду, анализировать и затем строить модели. Тебе предстоит планировать и ставить эксперименты, анализировать результаты и их статистическую значимость. Использовать feature engineering, model selection и fine tuning.</p> <p><strong>Ты подойдешь, если</strong></p> <ul> <li> <p>Знаешь Python, умеешь обрабатывать данные с помощью pandas, NumPy, Plotly.</p> </li> <li> <p>У тебя есть опыт работы с SQL.</p> </li> <li> <p>Есть опыт работы с методами машинного обучения и основными инструментами data science: Scikit-learn, XGBoost, CatBoost и т.п.</p> </li> <li> <p>Разбираешься в математической статистике, теории вероятностей и знаешь, как проводить A/B тестирования.</p> </li> </ul> <p><strong>Будет плюсом, если</strong></p> <ul> <li> <p>Ты понимаешь принципы работы нейросетей и уже имеешь опыт с одним или несколькими фреймворками для глубокого обучения: TensorFlow или PyTorch.</p> </li> <li> <p>Умеешь вводить модели машинного обучения в работу production.</p> </li> </ul> <p><strong>Что будет твоим в Точке</strong></p> <ul> <li> <p>Зарплата от 100 000 ₽. Расскажи на собеседовании, какая зарплата будет комфортной для тебя. А мы определим твой грейд по хард и софт скиллам и назовём точную сумму.</p> </li> <li> <p>Официальное трудоустройство и бесплатная страховка здоровья даже за границей.</p> </li> <li> <p>Удобный график: гибкое начало и окончание рабочего дня.</p> </li> <li> <p>Современный и уютный офис со спортзалом и библиотекой, кофе-поинтами, кухнями и зонами отдыха.</p> </li> <li> <p>Гибкие методы управления: мы используем Agile и SCRUM, чтобы каждый день создавать новое и быстро реагировать на изменения.</p> </li> <li> <p>Бесплатное корпоративное обучение: мы ездим на IT-конференции, собираемся на митапы, раздаем призы на хакатонах и проходим курсы за счёт компании.</p> </li> <li> <p>Возможность принимать решения без тысячи согласований и предлагать идеи: от простых до самых амбициозных.</p> </li> </ul> <p>И всё это в комфортных условиях без бюрократии, дресс-кода и начальников.</p></div>\n <div class="tmpl_hh_footer"></div>\n <p class="tmpl_hh_foonote">АО\xa0«Точка»</p>\n </div>\n',
'vacancy_constructor_template': None,
'key_skills': [{'name': 'аналитика'},
{'name': 'SQL'},
{'name': 'Python'},
{'name': 'Информационные технологии'},
{'name': 'Работа с базами данных'},
{'name': 'Математический анализ'},
{'name': 'NumPy'},
{'name': 'Математическая статистика'},
{'name': 'XGBoost'}],
'accept_handicapped': False,
'accept_kids': False,
'archived': False,
'response_url': None,
'specializations': [{'id': '17.751',
'name': 'Другое',
'profarea_id': '17',
'profarea_name': 'Продажи'},
{'id': '1.25',
'name': 'Аналитик',
'profarea_id': '1',
'profarea_name': 'Информационные технологии, интернет, телеком'},
{'id': '3.26',
'name': 'Аналитик',
'profarea_id': '3',
'profarea_name': 'Маркетинг, реклама, PR'},
{'id': '12.746',
'name': 'Другое',
'profarea_id': '12',
'profarea_name': 'Консультирование'}],
'professional_roles': [{'id': '10', 'name': 'Аналитик'}],
'code': None,
'hidden': False,
'quick_responses_allowed': False,
'driver_license_types': [],
'accept_incomplete_resumes': False,
'employer': {'id': '2324020',
'name': 'Точка',
'url': 'https://api.hh.ru/employers/2324020',
'alternate_url': 'https://hh.ru/employer/2324020',
'logo_urls': {'240': 'https://hhcdn.ru/employer-logo/3414734.jpeg',
'90': 'https://hhcdn.ru/employer-logo/3414733.jpeg',
'original': 'https://hhcdn.ru/employer-logo-original/743443.jpg'},
'vacancies_url': 'https://api.hh.ru/vacancies?employer_id=2324020',
'trusted': True},
'published_at': '2022-03-17T12:37:57+0300',
'created_at': '2022-03-17T12:37:57+0300',
'negotiations_url': None,
'suitable_resumes_url': None,
'apply_alternate_url': 'https://hh.ru/applicant/vacancy_response?vacancyId=49423067',
'has_test': False,
'test': None,
'alternate_url': 'https://hh.ru/vacancy/49423067',
'working_days': [],
'working_time_intervals': [],
'working_time_modes': [],
'accept_temporary': False}
Исследуем профессию Data Scientist. Найдите как можно больше вакансий по этой профессии в Москве. Учтите, что имеет смысл искать также по другим ключевым словам, например аналитик данных.
parametrs_for_text = ["Data Science", "Аналитик Данных", "Data Analyst", "Data Scientist"]
all_vacancies = pd.DataFrame([])
for i in range(0, 2):
j = 0
while True:
params = {
'text': parametrs_for_text[2 * i] + " OR " + parametrs_for_text[2 * i + 1],
'area': 1,
'page': j,
'per_page': 100
}
req = requests.get(URL, params)
data = json.loads(req.content.decode())
if not 'items' in data.keys():
break
j += 1
all_vacancies = pd.concat([pd.json_normalize(data['items']), all_vacancies], ignore_index=True)
sleep(0.5)
all_vacancies
| id | premium | name | has_test | response_letter_required | salary | response_url | sort_point_distance | published_at | created_at | ... | department | salary.from | salary.to | salary.currency | salary.gross | address | address.metro | employer.logo_urls | insider_interview.id | insider_interview.url | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 54029828 | False | Middle / Senior Java Developer (SberDevices) | False | False | NaN | None | None | 2022-03-18T09:40:22+0300 | 2022-03-18T09:40:22+0300 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 1 | 50332932 | False | Middle android-разработчик | False | False | NaN | None | None | 2022-03-15T11:45:41+0300 | 2022-03-15T11:45:41+0300 | ... | NaN | 200000.0 | NaN | RUR | False | NaN | NaN | NaN | NaN | NaN |
| 2 | 50673248 | False | SEO специалист (Senior / Lead) | False | False | NaN | None | None | 2022-02-28T14:29:34+0300 | 2022-02-28T14:29:34+0300 | ... | NaN | 130000.0 | NaN | RUR | False | NaN | NaN | NaN | NaN | NaN |
| 3 | 52899274 | False | Senior iOS-разработчик в команду мобильного пр... | False | False | NaN | None | None | 2022-03-18T13:49:51+0300 | 2022-03-18T13:49:51+0300 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 4 | 53218197 | False | Ведущий менеджер по маркетингу (VK) | False | False | NaN | None | None | 2022-03-01T22:33:31+0300 | 2022-03-01T22:33:31+0300 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 3655 | 53171872 | False | Quantitative Trader / Quantitative Analyst | False | False | NaN | None | None | 2022-03-18T14:09:03+0300 | 2022-03-18T14:09:03+0300 | ... | NaN | 3500.0 | NaN | USD | False | NaN | NaN | NaN | NaN | NaN |
| 3656 | 53169751 | False | Младший консультант/бизнес-аналитик | False | False | NaN | None | None | 2022-03-18T13:33:05+0300 | 2022-03-18T13:33:05+0300 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 3657 | 53804412 | False | Аналитик | False | False | NaN | None | None | 2022-03-17T10:43:44+0300 | 2022-03-17T10:43:44+0300 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 3658 | 53150521 | False | Старший аналитик НСМ | False | False | NaN | None | None | 2022-03-18T09:06:53+0300 | 2022-03-18T09:06:53+0300 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 3659 | 51710996 | False | Аналитик товарной категории | False | False | NaN | None | None | 2022-03-18T09:06:20+0300 | 2022-03-18T09:06:20+0300 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
3660 rows × 66 columns
В полученную выборку некоторые вакансии могли попасть несколько раз. Удалите дубликаты.
all_vacancies.drop_duplicates(subset=['id'], ignore_index=True, inplace = True)
all_vacancies
| id | premium | name | has_test | response_letter_required | salary | response_url | sort_point_distance | published_at | created_at | ... | department | salary.from | salary.to | salary.currency | salary.gross | address | address.metro | employer.logo_urls | insider_interview.id | insider_interview.url | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 54029828 | False | Middle / Senior Java Developer (SberDevices) | False | False | NaN | None | None | 2022-03-18T09:40:22+0300 | 2022-03-18T09:40:22+0300 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 1 | 50332932 | False | Middle android-разработчик | False | False | NaN | None | None | 2022-03-15T11:45:41+0300 | 2022-03-15T11:45:41+0300 | ... | NaN | 200000.0 | NaN | RUR | False | NaN | NaN | NaN | NaN | NaN |
| 2 | 50673248 | False | SEO специалист (Senior / Lead) | False | False | NaN | None | None | 2022-02-28T14:29:34+0300 | 2022-02-28T14:29:34+0300 | ... | NaN | 130000.0 | NaN | RUR | False | NaN | NaN | NaN | NaN | NaN |
| 3 | 52899274 | False | Senior iOS-разработчик в команду мобильного пр... | False | False | NaN | None | None | 2022-03-18T13:49:51+0300 | 2022-03-18T13:49:51+0300 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 4 | 53218197 | False | Ведущий менеджер по маркетингу (VK) | False | False | NaN | None | None | 2022-03-01T22:33:31+0300 | 2022-03-01T22:33:31+0300 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 3293 | 53171872 | False | Quantitative Trader / Quantitative Analyst | False | False | NaN | None | None | 2022-03-18T14:09:03+0300 | 2022-03-18T14:09:03+0300 | ... | NaN | 3500.0 | NaN | USD | False | NaN | NaN | NaN | NaN | NaN |
| 3294 | 53169751 | False | Младший консультант/бизнес-аналитик | False | False | NaN | None | None | 2022-03-18T13:33:05+0300 | 2022-03-18T13:33:05+0300 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 3295 | 53804412 | False | Аналитик | False | False | NaN | None | None | 2022-03-17T10:43:44+0300 | 2022-03-17T10:43:44+0300 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 3296 | 53150521 | False | Старший аналитик НСМ | False | False | NaN | None | None | 2022-03-18T09:06:53+0300 | 2022-03-18T09:06:53+0300 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 3297 | 51710996 | False | Аналитик товарной категории | False | False | NaN | None | None | 2022-03-18T09:06:20+0300 | 2022-03-18T09:06:20+0300 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
3298 rows × 66 columns
Загрузите подробное описание каждой вакансии и создайте удобную таблицу данных.
final_table = pd.DataFrame([], columns = ['id', 'employer.name', 'name', 'key_skills', 'schedule.name', 'description', 'salary.from', 'salary.to', 'salary.currency', 'salary.gross', 'lat', 'lng', 'experience.name'])
for i in tqdm(all_vacancies.index):
tmp_line = pd.DataFrame([], columns = ['id', 'employer.name', 'name', 'key_skills', 'schedule.name', 'description', 'salary.from', 'salary.to', 'salary.currency', 'salary.gross', 'lat', 'lng', 'experience.name'])
vacancy = all_vacancies['id'].iloc[i]
vacancy_url = f'https://api.hh.ru/vacancies/{vacancy}'
req = requests.get(vacancy_url)
vacancy_info = json.loads(req.content.decode())
df_vacancy = pd.json_normalize(vacancy_info)
tmp_line[['id', 'name', 'key_skills', 'schedule.name', 'description', 'experience.name']] = df_vacancy[['id', 'name', 'key_skills', 'schedule.name', 'description', 'experience.name']]
if 'salary.from' in df_vacancy.columns:
tmp_line[['salary.from', 'salary.to', 'salary.currency', 'salary.gross']] = df_vacancy[['salary.from', 'salary.to', 'salary.currency', 'salary.gross']]
tmp_line[['employer.name', 'lat', 'lng']] = all_vacancies[['employer.name', 'address.lat', 'address.lng']].iloc[i]
final_table = pd.concat([final_table, tmp_line], ignore_index=True)
sleep(0.5)
100%|███████████████████████████████████████████████████████████| 3298/3298 [41:43<00:00, 1.32it/s]
final_table['key_skills'] = list(map(lambda x: [y['name'] for y in x], final_table['key_skills']))
final_table[['address.metro.station_name', 'address.metro.line_name', 'address.metro.lat', 'address.metro.lng']] = all_vacancies[['address.metro.station_name', 'address.metro.line_name', 'address.metro.lat', 'address.metro.lng']]
final_table
| id | employer.name | name | key_skills | schedule.name | description | salary.from | salary.to | salary.currency | salary.gross | lat | lng | experience.name | address.metro.station_name | address.metro.line_name | address.metro.lat | address.metro.lng | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 54029828 | Сбербанк | Middle / Senior Java Developer (SberDevices) | [Java, Kotlin, Spring] | Полный день | <p>Приглашаем в нашу команду специалистов, кот... | NaN | NaN | NaN | NaN | 55.741338 | 37.531127 | От 3 до 6 лет | Кутузовская | Филевская | 55.740544 | 37.534100 |
| 1 | 50332932 | Константа | Middle android-разработчик | [MVP, RxJava, Room, Kotlin, MVVM] | Гибкий график | <p>Привет! Мы в Константе создаем различные пр... | 200000 | NaN | RUR | False | 55.785068 | 37.655580 | От 1 года до 3 лет | Красносельская | Сокольническая | 55.780014 | 37.666097 |
| 2 | 50673248 | ВБЦ | SEO специалист (Senior / Lead) | [SEO, Продвижение сайтов, JS, Java Script, Раб... | Полный день | <p><strong>Группа компаний «ВБЦ» – российская ... | 130000 | NaN | RUR | False | 55.751832 | 37.525270 | От 1 года до 3 лет | Тестовская | МЦД - 1 | 55.754292 | 37.531551 |
| 3 | 52899274 | Туту.ру | Senior iOS-разработчик в команду мобильного пр... | [Git, Swift, iOS, Adobe Photoshop, Sketch] | Полный день | <p>Наш ключевой продукт — это единое приложени... | NaN | NaN | NaN | NaN | 55.678458 | 37.632287 | От 1 года до 3 лет | Нагатинская | Серпуховско-Тимирязевская | 55.682099 | 37.620917 |
| 4 | 53218197 | VK | Ведущий менеджер по маркетингу (VK) | [Google Analytics, Яндекс.Метрика, Работа с бо... | Удаленная работа | <p>Мы являемся частью экосистемы VK и занимаем... | NaN | NaN | NaN | NaN | NaN | NaN | От 3 до 6 лет | NaN | NaN | NaN | NaN |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 3293 | 53171872 | Alber Blanc | Quantitative Trader / Quantitative Analyst | [Python, C/C++, Математическая статистика, Ана... | Гибкий график | <p><strong>Мы, в Alber Blanc, занимаемся высок... | 3500 | None | USD | False | NaN | NaN | От 1 года до 3 лет | NaN | NaN | NaN | NaN |
| 3294 | 53169751 | Т1 Консалтинг | Младший консультант/бизнес-аналитик | [Английский язык, MS PowerPoint, Подготовка пр... | Полный день | <p><strong>Т1 Консалтинг – </strong>российская... | NaN | None | NaN | NaN | 55.708354 | 37.652705 | От 1 года до 3 лет | Автозаводская | Замоскворецкая | 55.706634 | 37.657008 |
| 3295 | 53804412 | ДИАМЕД-ФАРМА | Аналитик | [] | Полный день | <p><strong>«ДИАМЕД - фарма» </strong>- совреме... | NaN | None | NaN | NaN | 55.840245 | 37.492024 | От 3 до 6 лет | NaN | NaN | NaN | NaN |
| 3296 | 53150521 | ИНТЕР РАО ИТ | Старший аналитик НСМ | [Обучение и развитие, Управление проектами, At... | Полный день | <p>Приглашаем на работу в ИТ-компанию, входящу... | NaN | None | NaN | NaN | 55.730152 | 37.567815 | От 3 до 6 лет | Спортивная | Сокольническая | 55.722388 | 37.562041 |
| 3297 | 51710996 | O'STIN | Аналитик товарной категории | [] | Полный день | <p><strong>Мы ожидаем:</strong></p> <ul> <li>M... | NaN | None | NaN | NaN | 55.792589 | 37.527588 | От 1 года до 3 лет | Аэропорт | Замоскворецкая | 55.800441 | 37.530477 |
3298 rows × 17 columns
final_table.to_excel("vacancy_description.xlsx")
all_vacancies.to_excel("all_vacancies.xlsx")
Полученную таблицу необходимо сохранить в формате xlsx и отправить боту вместе с решением.
Вопрос 1. Сколько сейчас доступно вакансий по вашему запросу?
final_table.shape[0]
3298
Вопрос 2. Какие навыки чаще всего встречаются в вакансиях по данной специальности?
Для этого найдите соответствующее поле в данных, проанализируйте его и составьте список навыков и количество упоминаний каждого. Визуализируйте полученную информацию по топ-15 навыков.
table_skills = {}
for skills in final_table["key_skills"]:
for skill in skills:
if table_skills.get(skill) == None:
table_skills[skill] = 1
continue
table_skills[skill] += 1
df_skills = pd.DataFrame.from_dict(table_skills, orient='index').reset_index().rename(columns={'index' : 'навыки', 0 : 'кол-во'}).sort_values(by='кол-во', ascending = False)
df_skills.head(15)
| навыки | кол-во | |
|---|---|---|
| 29 | SQL | 1130 |
| 71 | Python | 756 |
| 101 | Английский язык | 493 |
| 36 | Анализ данных | 415 |
| 61 | Аналитическое мышление | 411 |
| 81 | MS PowerPoint | 406 |
| 75 | Управление проектами | 232 |
| 28 | Работа с большим объемом информации | 206 |
| 30 | PostgreSQL | 192 |
| 85 | MS SQL | 186 |
| 82 | Бизнес-анализ | 179 |
| 21 | Git | 176 |
| 132 | MS Excel | 169 |
| 137 | Tableau | 167 |
| 212 | Data Analysis | 163 |
with sns.axes_style('whitegrid'):
plt.figure(figsize=(15, 10))
sns.barplot(y="навыки", x="кол-во", data=df_skills.head(15));
plt.title("Топ-15 навыков для Аналитика Данных", fontweight = "bold", fontsize = 19)
По топ навыкам мы можем сказать, что наш запрос был успешным. Ведь для аналитика данных и вправду необходимы выше описанные навыки. Как мы видим компании больше всего требуют знания SQL, Python, Английский язык и Анализ данных.
Вопрос 3. Какую зарплату готовы платить работодатели? Соберите некоторым образом статистику и постройте гистограмму.
При работе с данными о заработной плате обратите внимание на валюту и gross/net.
df_salary = final_table[(final_table['salary.from'] == final_table['salary.from']) | (final_table['salary.to'] == final_table['salary.to'])]
df_salary = df_salary[['salary.from', 'salary.to', 'salary.currency', 'salary.gross']]
df_salary
| salary.from | salary.to | salary.currency | salary.gross | |
|---|---|---|---|---|
| 1 | 200000 | None | RUR | False |
| 2 | 130000 | None | RUR | False |
| 6 | 180 | 230000 | RUR | False |
| 22 | 200000 | 250000 | RUR | False |
| 28 | None | 6000 | USD | True |
| ... | ... | ... | ... | ... |
| 3281 | 120000 | 260000 | RUR | False |
| 3282 | 250000 | 300000 | RUR | False |
| 3286 | 80000 | None | RUR | True |
| 3288 | 80000 | None | RUR | True |
| 3293 | 3500 | None | USD | False |
895 rows × 4 columns
mean_salary = []
for i in df_salary.index:
sal = 0
if df_salary['salary.from'][i] == None:
sal = df_salary['salary.to'][i]
elif df_salary['salary.to'][i] == None:
sal = df_salary['salary.from'][i]
else:
sal = (df_salary['salary.from'][i] + df_salary['salary.to'][i]) / 2
if df_salary['salary.currency'][i] == 'USD':
sal *= 111
elif df_salary['salary.currency'][i] == 'EUR':
sal *= 122
if df_salary['salary.gross'][i] == True:
sal *= 0.87
mean_salary.append(sal)
df_salary["salary.mean"] = mean_salary
df_salary
| salary.from | salary.to | salary.currency | salary.gross | salary.mean | |
|---|---|---|---|---|---|
| 1 | 200000 | None | RUR | False | 200000.0 |
| 2 | 130000 | None | RUR | False | 130000.0 |
| 6 | 180 | 230000 | RUR | False | 115090.0 |
| 22 | 200000 | 250000 | RUR | False | 225000.0 |
| 28 | None | 6000 | USD | True | 579420.0 |
| ... | ... | ... | ... | ... | ... |
| 3281 | 120000 | 260000 | RUR | False | 190000.0 |
| 3282 | 250000 | 300000 | RUR | False | 275000.0 |
| 3286 | 80000 | None | RUR | True | 69600.0 |
| 3288 | 80000 | None | RUR | True | 69600.0 |
| 3293 | 3500 | None | USD | False | 388500.0 |
895 rows × 5 columns
with sns.axes_style('whitegrid'):
plt.figure(figsize=(13, 8))
plt.xlim((0, 0.7 * 10**6))
sns.histplot(data=df_salary['salary.mean'], alpha = 0.8)
plt.ylabel("кол-во работодателей")
plt.xlabel("зарплата")
plt.title("Кол-во вакансий в области Data Science разных зарплат\n", fontweight = "bold", fontsize = 19)
По гистограмме видно, что средняя зарплата Аналитика данных $90000$ - $150000$. Также многие работодатели готовы платить от $200000$ до $300000$, что не может нас не радовать.
parametrs_for_text = ['Венчурный капитал', 'Финансовый аналитик', 'Инвестиционный аналитик', 'Венчурный инвестор']
all_vacancies_ml = pd.DataFrame([])
for i in range(0, 2):
j = 0
while True:
params = {
'text': parametrs_for_text[2 * i] + " OR " + parametrs_for_text[2 * i + 1],
'area': 1,
'page': j,
'per_page': 100
}
req = requests.get(URL, params)
data = json.loads(req.content.decode())
if not 'items' in data.keys():
break
j += 1
all_vacancies_ml = pd.concat([pd.json_normalize(data['items']), all_vacancies_ml], ignore_index=True)
sleep(0.5)
all_vacancies_ml.drop_duplicates(subset=['id'], ignore_index=True, inplace = True)
all_vacancies_ml
| id | premium | name | department | has_test | response_letter_required | address | response_url | sort_point_distance | published_at | ... | address.metro.lng | address.metro_stations | address.id | address.metro | employer.logo_urls | department.id | department.name | insider_interview.id | insider_interview.url | immediate_redirect_url | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 53265736 | False | Инвестиционный аналитик (сейлз) | NaN | False | False | NaN | None | None | 2022-03-02T12:01:25+0300 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 1 | 51783161 | False | Инвестиционный аналитик/Инвестиционный менеджер | NaN | False | False | NaN | None | None | 2022-02-25T09:40:02+0300 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 2 | 52023549 | False | Консультант / инвестиционный аналитик | NaN | False | False | NaN | None | None | 2022-03-14T14:22:05+0300 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 3 | 51773289 | False | Инвестиционный аналитик (финансовое моделирова... | NaN | False | False | NaN | None | None | 2022-03-15T11:46:15+0300 | ... | 37.562271 | [{'station_name': 'Улица 1905 года', 'line_nam... | 2919650 | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 4 | 50342220 | False | Младший инвестиционный аналитик/оценщик (недви... | NaN | False | False | NaN | None | None | 2022-03-15T11:17:14+0300 | ... | NaN | [] | 3531439 | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 1546 | 48266162 | False | Главный экономист (Методология и управление из... | NaN | False | False | NaN | None | None | 2022-03-15T13:04:16+0300 | ... | 37.680726 | [{'station_name': 'Площадь Ильича', 'line_name... | 1446 | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 1547 | 53687844 | False | Руководитель направления "Финансовый анализ" | NaN | False | False | NaN | None | None | 2022-03-11T13:14:33+0300 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 1548 | 54036890 | False | Младший финансовый менеджер/Аналитик | NaN | False | False | NaN | None | None | 2022-03-18T11:35:20+0300 | ... | NaN | [] | 3817280 | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 1549 | 53548751 | False | Финансовый аналитик (Food / Nonfood) | NaN | False | False | NaN | None | None | 2022-03-09T09:35:03+0300 | ... | NaN | [] | 643651 | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 1550 | 53369065 | False | Финансовый аналитик | NaN | False | False | NaN | None | None | 2022-03-04T12:34:41+0300 | ... | NaN | [] | 3692511 | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
1551 rows × 67 columns
final_table_ml = pd.DataFrame([], columns = ['id', 'employer.name', 'name', 'key_skills', 'schedule.name', 'description', 'salary.from', 'salary.to', 'salary.currency', 'salary.gross', 'lat', 'lng', 'experience.name'])
for i in tqdm(all_vacancies_ml.index):
tmp_line = pd.DataFrame([], columns = ['id','employer.name', 'name', 'key_skills', 'schedule.name', 'description', 'salary.from', 'salary.to', 'salary.currency', 'salary.gross', 'lat', 'lng', 'experience.name'])
vacancy = all_vacancies_ml['id'].iloc[i]
vacancy_url = f'https://api.hh.ru/vacancies/{vacancy}'
req = requests.get(vacancy_url)
vacancy_info = json.loads(req.content.decode())
df_vacancy = pd.json_normalize(vacancy_info)
tmp_line[['id', 'name', 'key_skills', 'schedule.name', 'description', 'experience.name']] = df_vacancy[['id', 'name', 'key_skills', 'schedule.name', 'description', 'experience.name']]
if 'salary.from' in df_vacancy.columns:
tmp_line[['salary.from', 'salary.to', 'salary.currency', 'salary.gross']] = df_vacancy[['salary.from', 'salary.to', 'salary.currency', 'salary.gross']]
tmp_line[['lat', 'lng', 'employer.name']] = all_vacancies_ml[['address.lat', 'address.lng', 'employer.name']].iloc[i]
final_table_ml = pd.concat([final_table_ml, tmp_line], ignore_index=True)
sleep(0.5)
100%|███████████████████████████████████████████████████████████| 1551/1551 [17:43<00:00, 1.46it/s]
final_table_ml['key_skills'] = list(map(lambda x: [y['name'] for y in x], final_table_ml['key_skills']))
final_table_ml[['address.metro.station_name', 'address.metro.line_name', 'address.metro.lat', 'address.metro.lng']] = all_vacancies_ml[['address.metro.station_name', 'address.metro.line_name', 'address.metro.lat', 'address.metro.lng']]
final_table_ml
| id | employer.name | name | key_skills | schedule.name | description | salary.from | salary.to | salary.currency | salary.gross | lat | lng | experience.name | address.metro.station_name | address.metro.line_name | address.metro.lat | address.metro.lng | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 53265736 | Cornerstone Russia | Инвестиционный аналитик (сейлз) | [Активные продажи, работа с VIP клиентами, Фон... | Гибкий график | <p>Крупный российский банк (ТОП 20 самых надеж... | None | 250000 | RUR | True | NaN | NaN | От 1 года до 3 лет | NaN | NaN | NaN | NaN |
| 1 | 51783161 | Скайлав Рус | Инвестиционный аналитик/Инвестиционный менеджер | [Английский язык, Анализ инвестиционных проект... | Полный день | <strong>Обязанности:</strong> <ul> <li> <p>Соз... | None | NaN | NaN | NaN | NaN | NaN | Нет опыта | NaN | NaN | NaN | NaN |
| 2 | 52023549 | КБ Стрелка | Консультант / инвестиционный аналитик | [Английский язык, Управление проектами, Ведени... | Полный день | <p>КБ Стрелка — ведущий консультант в области ... | None | NaN | NaN | NaN | NaN | NaN | От 1 года до 3 лет | NaN | NaN | NaN | NaN |
| 3 | 51773289 | АПХ ЭКО-культура | Инвестиционный аналитик (финансовое моделирова... | [Финансовый анализ, Анализ инвестиционных прое... | Полный день | <p>Агропромышленный холдинг <strong>«ЭКО-культ... | None | NaN | NaN | NaN | 55.754968 | 37.509262 | Нет опыта | Улица 1905 года | Таганско-Краснопресненская | 55.763944 | 37.562271 |
| 4 | 50342220 | Sminex | Младший инвестиционный аналитик/оценщик (недви... | [] | Полный день | <p><strong>Sminex</strong></p> <p>Приоритетная... | None | NaN | NaN | NaN | 55.742706 | 37.617734 | Нет опыта | NaN | NaN | NaN | NaN |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 1546 | 48266162 | Промсвязьбанк | Главный экономист (Методология и управление из... | [] | Полный день | <p><strong>Ключевые задачи:</strong></p> <ul> ... | NaN | NaN | NaN | NaN | 55.735876 | 37.710896 | От 1 года до 3 лет | Площадь Ильича | Калининская | 55.747115 | 37.680726 |
| 1547 | 53687844 | Х5 Group | Руководитель направления "Финансовый анализ" | [Работа в команде, Деловая коммуникация, Управ... | Полный день | <strong>Обязанности:</strong> <ul> <li>Выполне... | NaN | NaN | NaN | NaN | NaN | NaN | От 3 до 6 лет | NaN | NaN | NaN | NaN |
| 1548 | 54036890 | Центр Орбита | Младший финансовый менеджер/Аналитик | [Финансовый анализ, Бюджетирование, Бухгалтерс... | Полный день | <p><strong>Группа компаний Орбита - партнер ве... | None | 120000 | RUR | True | 55.748143 | 37.540488 | От 3 до 6 лет | NaN | NaN | NaN | NaN |
| 1549 | 53548751 | Р-Фарм | Финансовый аналитик (Food / Nonfood) | [BPMN, Финансовый контроль, Финансовый контрол... | Полный день | <p><strong>Задачи:</strong></p> <p>Импорт и оп... | NaN | NaN | NaN | NaN | 55.775869 | 37.612057 | От 3 до 6 лет | NaN | NaN | NaN | NaN |
| 1550 | 53369065 | Центр хранения и анализа больших данных | Финансовый аналитик | [Финансовый анализ, Анализ инвестиционных прое... | Полный день | <p>Вакансия для тех, кто хочет научиться привл... | 70000 | 100000 | RUR | False | 55.696514 | 37.526483 | От 1 года до 3 лет | NaN | NaN | NaN | NaN |
1551 rows × 17 columns
final_table_ml.to_excel("vacancy_description_ml.xlsx")
Сколько сейчас доступно вакансий по вашему запросу?
final_table_ml.shape[0]
1551
Какие навыки чаще всего встречаются в вакансиях по данной специальности?
Для этого найдите соответствующее поле в данных, проанализируйте его и составьте список навыков и количество упоминаний каждого. Визуализируйте полученную информацию по топ-15 навыков.
table_skills_ml = {}
for skills in final_table_ml["key_skills"]:
for skill in skills:
if table_skills_ml.get(skill) == None:
table_skills_ml[skill] = 1
continue
table_skills_ml[skill] += 1
df_skills_ml = pd.DataFrame.from_dict(table_skills_ml, orient='index').reset_index().rename(columns={'index' : 'навыки', 0 : 'кол-во'}).sort_values(by='кол-во', ascending = False)
df_skills_ml.head(15)
| навыки | кол-во | |
|---|---|---|
| 13 | Финансовый анализ | 754 |
| 49 | Управленческая отчетность | 321 |
| 9 | MS PowerPoint | 313 |
| 113 | Финансовая отчетность | 309 |
| 381 | Бюджетирование | 295 |
| 5 | Английский язык | 250 |
| 421 | Финансовый контроль | 235 |
| 18 | Анализ финансовых показателей | 160 |
| 112 | Аналитическое мышление | 150 |
| 161 | MS Excel | 142 |
| 7 | Финансовое моделирование | 137 |
| 209 | Финансовое планирование | 126 |
| 29 | Экономический анализ | 126 |
| 15 | Анализ текущих финансовых показателей | 125 |
| 38 | Работа с большим объемом информации | 124 |
with sns.axes_style('whitegrid'):
plt.figure(figsize=(15, 10))
sns.barplot(y="навыки", x="кол-во", data=df_skills_ml.head(15));
plt.title("Топ-15 навыков для Инвестиционного Аналитика", fontweight = "bold", fontsize = 19)
Тут мы можем сказать, что от инвестиционного аналитика больше всего требуют знания Финансового анализа, Управленческая отчетность, MS PowerPoint и Финансовая отчетность.
df_salary_ml = final_table_ml[(final_table_ml['salary.from'] == final_table_ml['salary.from']) | (final_table_ml['salary.to'] == final_table_ml['salary.to'])]
df_salary_ml = df_salary_ml[['salary.from', 'salary.to', 'salary.currency', 'salary.gross']]
df_salary_ml
| salary.from | salary.to | salary.currency | salary.gross | |
|---|---|---|---|---|
| 0 | None | 250000 | RUR | True |
| 5 | None | 2500 | EUR | True |
| 8 | 60000 | 80000 | RUR | False |
| 16 | None | 6600 | EUR | False |
| 25 | 100000 | 120000 | RUR | True |
| ... | ... | ... | ... | ... |
| 1538 | 90000 | 115000 | RUR | True |
| 1543 | 100000 | None | RUR | False |
| 1544 | 100000 | 300000 | RUR | True |
| 1548 | None | 120000 | RUR | True |
| 1550 | 70000 | 100000 | RUR | False |
512 rows × 4 columns
mean_salary_ml = []
for i in df_salary_ml.index:
sal = 0
if df_salary_ml['salary.from'][i] == None:
sal = df_salary_ml['salary.to'][i]
elif df_salary_ml['salary.to'][i] == None:
sal = df_salary_ml['salary.from'][i]
else:
sal = (df_salary_ml['salary.from'][i] + df_salary_ml['salary.to'][i]) / 2
if df_salary_ml['salary.currency'][i] == 'USD':
sal *= 111
elif df_salary_ml['salary.currency'][i] == 'EUR':
sal *= 122
if df_salary_ml['salary.gross'][i] == True:
sal *= 0.87
mean_salary_ml.append(sal)
df_salary_ml["salary.mean"] = mean_salary_ml
df_salary_ml
| salary.from | salary.to | salary.currency | salary.gross | salary.mean | |
|---|---|---|---|---|---|
| 0 | None | 250000 | RUR | True | 217500.0 |
| 5 | None | 2500 | EUR | True | 265350.0 |
| 8 | 60000 | 80000 | RUR | False | 70000.0 |
| 16 | None | 6600 | EUR | False | 805200.0 |
| 25 | 100000 | 120000 | RUR | True | 95700.0 |
| ... | ... | ... | ... | ... | ... |
| 1538 | 90000 | 115000 | RUR | True | 89175.0 |
| 1543 | 100000 | None | RUR | False | 100000.0 |
| 1544 | 100000 | 300000 | RUR | True | 174000.0 |
| 1548 | None | 120000 | RUR | True | 104400.0 |
| 1550 | 70000 | 100000 | RUR | False | 85000.0 |
512 rows × 5 columns
with sns.axes_style('whitegrid'):
plt.figure(figsize=(13, 8))
plt.xlim((0, 0.4 * 10**6))
sns.histplot(data=df_salary_ml['salary.mean'], alpha = 0.8)
plt.ylabel("кол-во работодателей")
plt.xlabel("средняя зарплата")
plt.title("Кол-во вакансий в области инвестиционного анализа разных зарплат\n", fontweight = "bold", fontsize = 19)
По данной гистограмме сразу можно сказать, что средняя зарплата $90000$ - $100000$. Тут видно, что мало работодателей готовы платить выше $150000$.
Вывод: 1) Отдельно выводы по каждой профессии написаны под каждым графиком.
2) Теперь давайте сравним результаты анализа профессии "Аналитик данных" и "Инвестиционный аналитик":
а) Кол-во вакансий на аналитика данных намного больше, чем на инвестиционного аналитика. Это показывает, что сейчас огромный спроси на аналитиков данных.
б) Средняя зарплата аналитиков данных больше, чем у инвестиционного аналитика. Высокая зарплата у инвестиционного аналитика встречается реже, чем у аналитика данных. Это может быть связано с тем, что аналитиков данных меньше на рынке услуг, чем инвестиционных аналитиков + проффесия современная, новая, мало хороших специалистов, профессионалов.
Для одной из рассмотренных ранее профессий ответьте на следующие вопросы:
Не забудьте про визуализацию, для этого используйте библиотеку plotly. В частности, постройте распределений вакансий на карте.
Для построения последних двух графиков вам могут понадобиться внешние данные.
df = pd.read_excel('vacancy_description.xlsx')
df.drop(columns = ['Unnamed: 0'], inplace=True)
df
| id | employer.name | name | key_skills | schedule.name | description | salary.from | salary.to | salary.currency | salary.gross | lat | lng | experience.name | address.metro.station_name | address.metro.line_name | address.metro.lat | address.metro.lng | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 54029828 | Сбербанк | Middle / Senior Java Developer (SberDevices) | ['Java', 'Kotlin', 'Spring'] | Полный день | <p>Приглашаем в нашу команду специалистов, кот... | NaN | NaN | NaN | NaN | 55.741338 | 37.531127 | От 3 до 6 лет | Кутузовская | Филевская | 55.740544 | 37.534100 |
| 1 | 50332932 | Константа | Middle android-разработчик | ['MVP', 'RxJava', 'Room', 'Kotlin', 'MVVM'] | Гибкий график | <p>Привет! Мы в Константе создаем различные пр... | 200000.0 | NaN | RUR | 0.0 | 55.785068 | 37.655580 | От 1 года до 3 лет | Красносельская | Сокольническая | 55.780014 | 37.666097 |
| 2 | 50673248 | ВБЦ | SEO специалист (Senior / Lead) | ['SEO', 'Продвижение сайтов', 'JS', 'Java Scri... | Полный день | <p><strong>Группа компаний «ВБЦ» – российская ... | 130000.0 | NaN | RUR | 0.0 | 55.751832 | 37.525270 | От 1 года до 3 лет | Тестовская | МЦД - 1 | 55.754292 | 37.531551 |
| 3 | 52899274 | Туту.ру | Senior iOS-разработчик в команду мобильного пр... | ['Git', 'Swift', 'iOS', 'Adobe Photoshop', 'Sk... | Полный день | <p>Наш ключевой продукт — это единое приложени... | NaN | NaN | NaN | NaN | 55.678458 | 37.632287 | От 1 года до 3 лет | Нагатинская | Серпуховско-Тимирязевская | 55.682099 | 37.620917 |
| 4 | 53218197 | VK | Ведущий менеджер по маркетингу (VK) | ['Google Analytics', 'Яндекс.Метрика', 'Работа... | Удаленная работа | <p>Мы являемся частью экосистемы VK и занимаем... | NaN | NaN | NaN | NaN | NaN | NaN | От 3 до 6 лет | NaN | NaN | NaN | NaN |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 3293 | 53171872 | Alber Blanc | Quantitative Trader / Quantitative Analyst | ['Python', 'C/C++', 'Математическая статистика... | Гибкий график | <p><strong>Мы, в Alber Blanc, занимаемся высок... | 3500.0 | NaN | USD | 0.0 | NaN | NaN | От 1 года до 3 лет | NaN | NaN | NaN | NaN |
| 3294 | 53169751 | Т1 Консалтинг | Младший консультант/бизнес-аналитик | ['Английский язык', 'MS PowerPoint', 'Подготов... | Полный день | <p><strong>Т1 Консалтинг – </strong>российская... | NaN | NaN | NaN | NaN | 55.708354 | 37.652705 | От 1 года до 3 лет | Автозаводская | Замоскворецкая | 55.706634 | 37.657008 |
| 3295 | 53804412 | ДИАМЕД-ФАРМА | Аналитик | [] | Полный день | <p><strong>«ДИАМЕД - фарма» </strong>- совреме... | NaN | NaN | NaN | NaN | 55.840245 | 37.492024 | От 3 до 6 лет | NaN | NaN | NaN | NaN |
| 3296 | 53150521 | ИНТЕР РАО ИТ | Старший аналитик НСМ | ['Обучение и развитие', 'Управление проектами'... | Полный день | <p>Приглашаем на работу в ИТ-компанию, входящу... | NaN | NaN | NaN | NaN | 55.730152 | 37.567815 | От 3 до 6 лет | Спортивная | Сокольническая | 55.722388 | 37.562041 |
| 3297 | 51710996 | O'STIN | Аналитик товарной категории | [] | Полный день | <p><strong>Мы ожидаем:</strong></p> <ul> <li>M... | NaN | NaN | NaN | NaN | 55.792589 | 37.527588 | От 1 года до 3 лет | Аэропорт | Замоскворецкая | 55.800441 | 37.530477 |
3298 rows × 17 columns
Для начала поймем, какой опыт требуют от Аналитика Данных наши работодатели.
df['experience.name'].unique()
array(['От 3 до 6 лет', 'От 1 года до 3 лет', 'Более 6 лет', 'Нет опыта'],
dtype=object)
min_experience = list(map(lambda x: int(x[3]) if x[:2] == 'От' else (0 if x == 'Нет опыта' else 6), df['experience.name']))
with sns.axes_style('whitegrid'):
plt.figure(figsize=(13, 8))
sns.histplot(data=min_experience, alpha = 0.8, discrete = True)
plt.ylabel("кол-во работодателей")
plt.xlabel("минимальный опыт")
plt.title("Зависимость кол-ва работодателей от требуемого минимального опыта\n", fontweight = "bold", fontsize = 19)
Теперь построим топ работодателей по числу вакансий.
top_company = df.groupby(by = ['employer.name']).count().reset_index().rename(columns = {'id' : 'vacancy_count'})[['employer.name', 'vacancy_count']].sort_values(by='vacancy_count', ascending = False)
top_company
| employer.name | vacancy_count | |
|---|---|---|
| 1330 | Сбербанк | 113 |
| 912 | Иннотех, Группа компаний | 42 |
| 1401 | Тинькофф | 36 |
| 1570 | билайн | 36 |
| 1035 | МТС | 36 |
| ... | ... | ... |
| 646 | Ананьева Оксана Васильевна | 1 |
| 645 | Аналитическое кредитное рейтинговое агентство ... | 1 |
| 643 | Аналитические решения | 1 |
| 642 | Аналитическая компания АРЭНСИ Фарма | 1 |
| 1573 | Мы занимаемся развитием и разработкой ра... | 1 |
1574 rows × 2 columns
with sns.axes_style('whitegrid'):
plt.figure(figsize=(15, 10))
sns.barplot(y="employer.name", x="vacancy_count", data=top_company.head(15));
plt.title("Топ работодателей по числу вакансий", fontweight = "bold", fontsize = 19)
plt.ylabel('компании')
plt.xlabel('число вакансий')
df_new = df.dropna(subset=['address.metro.line_name'])
df_new
| id | employer.name | name | key_skills | schedule.name | description | salary.from | salary.to | salary.currency | salary.gross | lat | lng | experience.name | address.metro.station_name | address.metro.line_name | address.metro.lat | address.metro.lng | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 54029828 | Сбербанк | Middle / Senior Java Developer (SberDevices) | ['Java', 'Kotlin', 'Spring'] | Полный день | <p>Приглашаем в нашу команду специалистов, кот... | NaN | NaN | NaN | NaN | 55.741338 | 37.531127 | От 3 до 6 лет | Кутузовская | Филевская | 55.740544 | 37.534100 |
| 1 | 50332932 | Константа | Middle android-разработчик | ['MVP', 'RxJava', 'Room', 'Kotlin', 'MVVM'] | Гибкий график | <p>Привет! Мы в Константе создаем различные пр... | 200000.0 | NaN | RUR | 0.0 | 55.785068 | 37.655580 | От 1 года до 3 лет | Красносельская | Сокольническая | 55.780014 | 37.666097 |
| 2 | 50673248 | ВБЦ | SEO специалист (Senior / Lead) | ['SEO', 'Продвижение сайтов', 'JS', 'Java Scri... | Полный день | <p><strong>Группа компаний «ВБЦ» – российская ... | 130000.0 | NaN | RUR | 0.0 | 55.751832 | 37.525270 | От 1 года до 3 лет | Тестовская | МЦД - 1 | 55.754292 | 37.531551 |
| 3 | 52899274 | Туту.ру | Senior iOS-разработчик в команду мобильного пр... | ['Git', 'Swift', 'iOS', 'Adobe Photoshop', 'Sk... | Полный день | <p>Наш ключевой продукт — это единое приложени... | NaN | NaN | NaN | NaN | 55.678458 | 37.632287 | От 1 года до 3 лет | Нагатинская | Серпуховско-Тимирязевская | 55.682099 | 37.620917 |
| 8 | 48175455 | Ренессанс Кредит | Руководитель группы разработки ДБО | [] | Полный день | <p><strong>IT</strong><strong>-команда «Ренесс... | NaN | NaN | NaN | NaN | 55.796273 | 37.599687 | От 3 до 6 лет | Савёловская | Серпуховско-Тимирязевская | 55.794054 | 37.587163 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 3284 | 53995806 | SberTech | Аналитик | ['UML', 'BPMN', 'IDEF', 'MS Visio', 'Моделиров... | Полный день | <p>Мы ищем аналитика в команду развития event-... | NaN | NaN | NaN | NaN | 55.695905 | 37.625361 | От 1 года до 3 лет | Тульская | Серпуховско-Тимирязевская | 55.709610 | 37.622569 |
| 3289 | 47325529 | Strategy Partners | Аналитик (стратегический консалтинг) | ['Английский язык', 'MS PowerPoint', 'Аналитич... | Полный день | <p><strong>Strategy Partners </strong>(http://... | NaN | NaN | NaN | NaN | 55.751262 | 37.586318 | От 1 года до 3 лет | Смоленская | Арбатско-Покровская | 55.747713 | 37.583802 |
| 3294 | 53169751 | Т1 Консалтинг | Младший консультант/бизнес-аналитик | ['Английский язык', 'MS PowerPoint', 'Подготов... | Полный день | <p><strong>Т1 Консалтинг – </strong>российская... | NaN | NaN | NaN | NaN | 55.708354 | 37.652705 | От 1 года до 3 лет | Автозаводская | Замоскворецкая | 55.706634 | 37.657008 |
| 3296 | 53150521 | ИНТЕР РАО ИТ | Старший аналитик НСМ | ['Обучение и развитие', 'Управление проектами'... | Полный день | <p>Приглашаем на работу в ИТ-компанию, входящу... | NaN | NaN | NaN | NaN | 55.730152 | 37.567815 | От 3 до 6 лет | Спортивная | Сокольническая | 55.722388 | 37.562041 |
| 3297 | 51710996 | O'STIN | Аналитик товарной категории | [] | Полный день | <p><strong>Мы ожидаем:</strong></p> <ul> <li>M... | NaN | NaN | NaN | NaN | 55.792589 | 37.527588 | От 1 года до 3 лет | Аэропорт | Замоскворецкая | 55.800441 | 37.530477 |
1298 rows × 17 columns
arr = df_new.groupby('address.metro.station_name').count().reset_index().rename(columns = {'id' : 'line_count'})[['address.metro.station_name', 'line_count']]
df_for_map = df_new.merge(arr, how = 'outer', on = 'address.metro.station_name')
df_for_map
| id | employer.name | name | key_skills | schedule.name | description | salary.from | salary.to | salary.currency | salary.gross | lat | lng | experience.name | address.metro.station_name | address.metro.line_name | address.metro.lat | address.metro.lng | line_count | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 54029828 | Сбербанк | Middle / Senior Java Developer (SberDevices) | ['Java', 'Kotlin', 'Spring'] | Полный день | <p>Приглашаем в нашу команду специалистов, кот... | NaN | NaN | NaN | NaN | 55.741338 | 37.531127 | От 3 до 6 лет | Кутузовская | Филевская | 55.740544 | 37.534100 | 43 |
| 1 | 53834398 | Сбербанк | Senior Python-разработчик в Цифровые поверхнос... | ['Python', 'Apache Kafka', 'Apache Ignite', 'A... | Полный день | <p>SberDevices — уникальное IT-пространство вн... | NaN | NaN | NaN | NaN | 55.741338 | 37.531127 | От 3 до 6 лет | Кутузовская | Филевская | 55.740544 | 37.534100 | 43 |
| 2 | 54029735 | Сбербанк | Java-разработчик (NLP / SberDevices) | ['Spring Framework', 'SQL', 'PostgreSQL', 'Jav... | Полный день | <p><strong>SberDevices</strong> — уникальное I... | NaN | NaN | NaN | NaN | 55.740421 | 37.532071 | От 1 года до 3 лет | Кутузовская | МЦК | 55.740833 | 37.533333 | 43 |
| 3 | 52685036 | Сбербанк | Qlik Sense разработчик | ['Hadoop', 'SQL', 'Java', 'Jenkins', 'PostgreS... | Полный день | <p>Наша задача реализовать новое прикладное ко... | NaN | NaN | NaN | NaN | 55.741338 | 37.531127 | От 1 года до 3 лет | Кутузовская | Филевская | 55.740544 | 37.534100 | 43 |
| 4 | 53834387 | Сбербанк | Python-разработчик в Цифровые поверхности Салю... | ['Python', 'Django Framework', 'PostgreSQL', '... | Полный день | <p>SberDevices — уникальное IT-пространство вн... | NaN | NaN | NaN | NaN | 55.741338 | 37.531127 | От 1 года до 3 лет | Кутузовская | Филевская | 55.740544 | 37.534100 | 43 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 1293 | 52563054 | Аналитическая компания АРЭНСИ Фарма | Специалист по обработке данных | ['MS Access', 'VBA', 'SQL', 'MS SQL', 'Базы да... | Полный день | <strong>Обязанности:</strong> <ul> <li>Работа ... | 50000.0 | 50000.0 | RUR | 0.0 | 55.864005 | 37.677292 | От 1 года до 3 лет | Бабушкинская | Калужско-Рижская | 55.870641 | 37.664341 | 1 |
| 1294 | 52801356 | БезРутины | Бизнес-аналитик (бизнес-ассистент с экспертным... | ['Аналитическое мышление', 'MS Excel', 'Сводны... | Полный день | <p><strong>GoFoods </strong>— российская компа... | 100000.0 | NaN | RUR | 0.0 | 55.585026 | 37.473626 | От 1 года до 3 лет | Коммунарка | Сокольническая | 55.559765 | 37.468716 | 1 |
| 1295 | 53988196 | RALF RINGER | Старший экономист-аналитик | ['План-фактный анализ бюджета', 'Анализ текущи... | Полный день | <strong>Обязанности:</strong> <ol> <li>Подгото... | NaN | 100000.0 | RUR | 0.0 | 55.814264 | 37.735117 | От 3 до 6 лет | Бульвар Рокоссовского | Сокольническая | 55.814916 | 37.732227 | 2 |
| 1296 | 51844115 | Черкизово, Группа предприятий | Бизнес-аналитик | ['Производственное планирование', 'Английский ... | Полный день | <strong>Обязанности:</strong> <ul> <li>Лидиров... | NaN | NaN | NaN | NaN | 55.820582 | 37.732916 | От 3 до 6 лет | Бульвар Рокоссовского | Сокольническая | 55.814916 | 37.732227 | 2 |
| 1297 | 53009958 | ТТФ | Инвестиционный аналитик | ['Финансовое моделирование', 'Финансовый анали... | Полный день | <strong>Обязанности:</strong> <p>- Финансовое ... | NaN | NaN | NaN | NaN | NaN | NaN | От 3 до 6 лет | Воробьевы горы | Сокольническая | 55.709169 | 37.557293 | 1 |
1298 rows × 18 columns
fig = px.scatter_mapbox(
df_for_map, # таблица с данными
lat='address.metro.lat', lon='address.metro.lng', # колонки с координатами
color = 'address.metro.line_name',
center=dict(lat=55.7737, lon=37.5717),
zoom=10,
size = df_for_map['line_count'],
size_max = 14,
mapbox_style='carto-positron'
)
fig.show();
Какие выводы можно сделать из построенных графиков?
1) В большинстве случаев работодатели требуют от сотрудников опыт $1$ год. Также много работодателей требует опыт от $1$ до $3$ лет. Очень мало компаний просят опыта больше $3$ лет. Связано это, скорее всего, с тем, что профессия относительно молодая.
2) Подавляющее большинство компаний связаны так или иначе с финансами, консалтингом и бизнес-сферой. Лишь малое количество специализируется в других отраслях (соц. сети, логистика и т.д.). Думаю, это связано с тем, что бизнес недавно только начал входить в сферу Анализа Данных, потому что до недавнего времени для бизнеса России это все было черным ящиком. Также можно выделить лидеров: Сбербанк, Иннотех, Тинькоф.
3) Большинство вакансий, мест работы сконцентрировано в пределах Мкада. Как правило между МКАДом и Садовым кольцом. Ну опять же, стоит понимать, что речь идет не о ресторанах и кафе, которые могут стремиться к центру для получения выгоды. От расположения компании мало что зависит. Поэтому такое "среднее" расположение между МКАДом и Садовым кольцом вполне себе уместно. Стоит также учесть то, что многие программисты работают на уделенке, их присутствие в офисе не везде обязательно.